## Array [not default]
### chunk
Chunks an array into smaller arrays of a specified size.
```javascript
const chunk = (arr, size) =>
  Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
    arr.slice(i * size, i * size + size)
  );
```
example
```javascript
chunk([1, 2, 3, 4, 5], 2); // [[1,2],[3,4],[5]]
```

### compact
Removes falsey values from an array.
```javascript
const compact = arr => arr.filter(Boolean);
```
example 
```javascript
compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34]); // [ 1, 2, 3, 'a', 's', 34 ]
```

### countBy
Groups the elements of an array based on the given function and returns the count of elements in each group.
```javascript
const countBy = (arr, fn) =>
  arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => {
    acc[val] = (acc[val] || 0) + 1;
    return acc;
  }, {});
```
example
```javascript
countBy([6.1, 4.2, 6.3], Math.floor); // {4: 1, 6: 2}
countBy(['one', 'two', 'three'], 'length'); // {3: 2, 5: 1}
```

### countOccurrences
Counts the occurrences of a value in an array.
```javascript
const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a + 0), 0);
```
example
```javascript
countOccurrences([1, 1, 2, 1, 2, 3], 1); // 3
```

### differenceBy [ie > 10]
Returns the difference between two arrays, after applying the provided function to each array element of both.
```javascript
const differenceBy = (a, b, fn) => {
  const s = new Set(b.map(v => fn(v)));
  return a.filter(x => !s.has(fn(x)));
};
```
example
```javascript
difference([1, 2, 3], [1, 2, 4]); // [3]
``` 

### differenceWith 
Filters out all values from an array for which the comparator function does not return true.
```javascript
const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1);
```
example
```javascript
differenceWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0], (a, b) => Math.round(a) === Math.round(b)); // [1, 1.2]
``` 

### drop 
Returns a new array with n elements removed from the left.
```javascript
const drop = (arr, n = 1) => arr.slice(n);
```
example
```javascript
drop([1, 2, 3]); // [2,3]
drop([1, 2, 3], 2); // [3]
drop([1, 2, 3], 42); // []
``` 

### dropRightWhile
Removes elements from the end of an array until the passed function returns true. Returns the remaining elements in the array.
```javascript
const dropRightWhile = (arr, func) => {
  while (arr.length > 0 && !func(arr[arr.length - 1])) arr = arr.slice(0, -1);
  return arr;
};
```
example
```javascript
dropRightWhile([1, 2, 3, 4], n => n < 3); // [1, 2]
```

### dropWhile
Removes elements in an array until the passed function returns true. Returns the remaining elements in the array.
```javascript
const dropWhile = (arr, func) => {
  while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
  return arr;
};
```
example
```javascript
dropWhile([1, 2, 3, 4], n => n >= 3); // [3,4]
```

### filterNonUnique
Filters out the non-unique values in an array.
```javascript
const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
```
example
```javascript
filterNonUnique([1, 2, 2, 3, 4, 4, 5]); // [1,3,5]
```

### findLast
Returns the last element for which the provided function returns a truthy value.
```javascript
const findLast = (arr, fn) => arr.filter(fn).slice(-1)[0];
```
example
```javascript
findLast([1, 2, 3, 4], n => n % 2 === 1); // 3
```

### findLastIndex
Returns the index of the last element for which the provided function returns a truthy value.
```javascript
const findLastIndex = (arr, fn) =>
  arr
    .map((val, i) => [i, val])
    .filter(val => fn(val[1], val[0], arr))
    .slice(-1)[0][0];
```
example
```javascript
findLastIndex([1, 2, 3, 4], n => n % 2 === 1); // 2 (index of the value 3)
```

### flatten
Flattens an array up to the specified depth.
```javascript
const flatten = (arr, depth = 1) =>
  depth !== 1
    ? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flatten(v, depth - 1) : v), [])
    : arr.reduce((a, v) => a.concat(v), [])
```
example
```javascript
flatten([1, [2], 3, 4]); // [1, 2, 3, 4]
flatten([1, [2, [3, [4, 5], 6], 7], 8], 2); // [1, 2, 3, [4, 5], 6, 7, 8]
```

### groupBy
Groups the elements of an array based on the given function.
```javascript
const groupBy = (arr, fn) =>
  arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => {
    acc[val] = (acc[val] || []).concat(arr[i]);
    return acc;
  }, {});
```
example
```javascript
groupBy([6.1, 4.2, 6.3], Math.floor); // {4: [4.2], 6: [6.1, 6.3]}
groupBy(['one', 'two', 'three'], 'length'); // {3: ['one', 'two'], 5: ['three']}
```

### intersectionWith
Returns a list of elements that exist in both arrays, using a provided comparator function.
```javascript
const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1);
```
example
```javascript
intersectionWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0, 3.9], (a, b) => Math.round(a) === Math.round(b)); // [1.5, 3, 0]
```

### nthElement
Returns the nth element of an array.
```javascript
const nthElement = (arr, n = 0) => (n > 0 ? arr.slice(n, n + 1) : arr.slice(n))[0];
```
example
```javascript
nthElement(['a', 'b', 'c'], 1); // 'b'
nthElement(['a', 'b', 'b'], -3); // 'a'
```

### remove
Removes elements from an array for which the given function returns false.
```javascript
const remove = (arr, func) =>
  Array.isArray(arr)
    ? arr.filter(func).reduce((acc, val) => {
        arr.splice(arr.indexOf(val), 1);
        return acc.concat(val);
      }, [])
    : [];
```
example
```javascript
remove([1, 2, 3, 4], n => n % 2 === 0); // [2, 4]
```

### shuffle
Randomizes the order of the values of an array, returning a new array.
```javascript
const shuffle = ([...arr]) => {
  let m = arr.length;
  while (m) {
    const i = Math.floor(Math.random() * m--);
    [arr[m], arr[i]] = [arr[i], arr[m]];
  }
  return arr;
};
```
example
```javascript
const foo = [1, 2, 3];
shuffle(foo); // [2,3,1], foo = [1,2,3]
```

### unionWith
Returns every element that exists in any of the two arrays once, using a provided comparator function.
```javascript
const unionWith = (a, b, comp) =>
  Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)]));
```
example
```javascript
unionWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0, 3.9], (a, b) => Math.round(a) === Math.round(b)); // [1, 1.2, 1.5, 3, 0, 3.9]
```

### uniqueElements
Returns all unique values of an array.
```javascript
const uniqueElements = arr => [...new Set(arr)];
```
example
```javascript
uniqueElements([1, 2, 2, 3, 4, 4, 5]); // [1,2,3,4,5]
```

### zip
Creates an array of elements, grouped based on the position in the original arrays.
```javascript
const zip = (...arrays) => {
  const maxLength = Math.max(...arrays.map(x => x.length));
  return Array.from({ length: maxLength }).map((_, i) => {
    return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]);
  });
};
```
example
```javascript
zip(['a', 'b'], [1, 2], [true, false]); // [['a', 1, true], ['b', 2, false]]
zip(['a'], [1, 2], [true, false]); // [['a', 1, true], [undefined, 2, false]]
```

### unzip
Creates an array of arrays, ungrouping the elements in an array produced by zip.
```javascript
const unzip = arr =>
  arr.reduce(
    (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc),
    Array.from({
      length: Math.max(...arr.map(x => x.length))
    }).map(x => [])
  );
```
example
```javascript
unzip([['a', 1, true], ['b', 2, false]]); //[['a', 'b'], [1, 2], [true, false]]
unzip([['a', 1, true], ['b', 2]]); //[['a', 'b'], [1, 2], [true]]
```